package com.example.denglu.util;


import com.example.denglu.config.exception.CommonError;
import com.example.denglu.config.exception.ErrorCode;
import com.example.denglu.config.exception.Errors;
import com.example.denglu.enums.ValidateRegexEnum;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 
 * Assertion utility class that assists in validating arguments.
 * @date  2017年11月14日
 */
public abstract class Assert {
	

	
	

	/**  */
	public static void isTrue(boolean expression, ErrorCode errorCode, Object... args) {
		if (!expression) {
			throw Errors.wrap(errorCode,args);
		}
	}

	/**  */
	public static void isNull(Object object, ErrorCode errorCode, Object... args) {
		if (object != null) {
			throw Errors.wrap(errorCode,args);
		}
	}

	/** (key_IS_NULL) */
	public static void isNotNull(Object object, ErrorCode errorCode, Object... args) {
		if (object == null) {
			throw Errors.wrap(errorCode,args);
		}
	}

	/**  */
	public static void hasLength(String text, ErrorCode errorCode, Object... args) {
		if (StringUtils.isEmpty(text)) {
			throw Errors.wrap(errorCode,args);
		}
	}

	/**  */
	public static void hasText(String text, ErrorCode errorCode, Object... args) {
		if (StringUtils.isBlank(text)) {
			throw Errors.wrap(errorCode,args);
		}
	}

	/**  */
	public static void doesNotContain(String textToSearch, String substring, ErrorCode errorCode, Object... args) {
		if (StringUtils.isNotBlank(textToSearch) && StringUtils.isNotBlank(substring)
				&& textToSearch.contains(substring)) {
			throw Errors.wrap(errorCode,args);
		}
	}

	/** */
	public static void notEmpty(Object[] array,  ErrorCode errorCode, Object... args) {
		if (ObjectUtils.isEmpty(array)) {
			throw Errors.wrap(errorCode,args);
		}
	}

	/**  */
	public static void noNullElements(Object[] array, ErrorCode errorCode, Object... args) {
		if (array != null) {
			for (Object element : array) {
				if (element == null) {
					throw Errors.wrap(errorCode,args);
				}
			}
		}
	}

	/**  */
	public static void notEmpty(Collection<?> collection, ErrorCode errorCode, Object... args) {
		if (CollectionUtils.isEmpty(collection)) {
			throw Errors.wrap(errorCode,args);
		}
	}

	/**  */
	public static void notEmpty(Map<?, ?> map,  ErrorCode errorCode, Object... args) {
		if (CollectionUtils.isEmpty(map)) {
			throw Errors.wrap(errorCode,args);
		}
	}

	/**  */
	public static void isInstanceOf(Class<?> type, Object obj, ErrorCode errorCode, Object... args) {
		isNotNull(type, errorCode);
		if (!type.isInstance(obj)) {
			throw Errors.wrap(errorCode,args);
		}
	}

	/**  */
	public static void isAssignable(Class<?> superType, Class<?> subType, ErrorCode errorCode, Object... args) {
		isNotNull(superType, errorCode);
		if (subType == null || !superType.isAssignableFrom(subType)) {
			throw Errors.wrap(errorCode,args);
		}
	}

	/** 空字符或NULL */
	public static void isBlank(String text, ErrorCode errorCode, Object... args) {
		if (StringUtils.isNotBlank(text)) {
			throw Errors.wrap(errorCode,args);
		}
	}

	/**
	 * 字符串不为空（null或长度为0）
	 **/
	public static void isNotEmpty(String text, ErrorCode errorCode, Object... args) {
		if (text == null || text.isEmpty()) {
			throw Errors.wrap(errorCode, args);
		}
	}

	/** 非空字符串(key_IS_NULL) */
	public static void isNotBlank(String text, ErrorCode errorCode, Object... args) {
		if (StringUtils.isBlank(text)) {
			throw Errors.wrap(errorCode,args);
		}
	}

	/** 允许最小值 */
	public static void min(Integer value, Integer min, ErrorCode errorCode, Object... args) {
		isNotNull(value, errorCode);
		if (value < min) {
			throw Errors.wrap(errorCode,args);
		}
	}

	/** 允许最大值 */
	public static void max(Integer value, Integer max, ErrorCode errorCode, Object... args) {
		isNotNull(value, errorCode);
		if (value > max) {
			throw Errors.wrap(errorCode,args);
		}
	}

	/** 允许值范围 */
	public static void range(Integer value, Integer min, Integer max, ErrorCode errorCode, Object... args) {
		min(value, min, errorCode);
		max(value, max, errorCode);
	}

	/** 允许最小值 */
	public static void min(Float value, Float min,  ErrorCode errorCode, Object... args) {
		isNotNull(value, errorCode);
		if (value < min) {
			throw Errors.wrap(errorCode,args);
		}
	}

	/** 允许最大值 */
	public static void max(Float value, Float max,  ErrorCode errorCode, Object... args) {
		isNotNull(value, errorCode);
		if (value > max) {
			throw Errors.wrap(errorCode,args);
		}
	}

	/** 允许值范围 */
	public static void range(Float value, Float min, Float max, ErrorCode errorCode, Object... args) {
		min(value, min, errorCode);
		max(value, max, errorCode);
	}

	/** 允许最小值 */
	public static void min(Double value, Double min,ErrorCode errorCode, Object... args) {
		isNotNull(value, errorCode);
		if (value < min) {
			throw Errors.wrap(errorCode,args);
		}
	}

	/** 允许最大值 */
	public static void max(Double value, Double max, ErrorCode errorCode, Object... args) {
		isNotNull(value, errorCode);
		if (value > max) {
			throw Errors.wrap(errorCode,args);
		}
	}

	/** 允许值范围 */
	public static void range(Double value, Double min, Double max, ErrorCode errorCode, Object... args) {
		min(value, min, errorCode);
		max(value, max, errorCode);
	}

	/** 字符长度(key_LENGTH) */
	public static void length(String text, Integer min, Integer max, ErrorCode errorCode, Object... args) {
		isNotNull(text, errorCode);
		if (min != null && text.length() < min) {
			throw Errors.wrap(errorCode,min,max,args);
		}
		if (max != null && text.length() > max) {
			throw Errors.wrap(errorCode,min,max,args);
		}
	}

	/** 未来某一天 */
	public static void future(Date date, String key,ErrorCode errorCode, Object... args) {
		if (date != null && date.compareTo(new Date()) <= 0) {
			throw Errors.wrap(errorCode,args);
		}
	}

	/** 身份证 */
	public static void idCard(String text,ErrorCode errorCode, Object... args) {
		if (!IDCardUtil.isIdentity(text)) {
			throw Errors.wrap(errorCode,args);
		}
	}

	/** 邮箱 */
	public static void email(String text,ErrorCode errorCode, Object... args) {
		String regex = "^([a-z0-9A-Z]+[-|_|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$";
		pattern(text, regex, true, errorCode,args);
	}

	/** 手机号 */
	public static void mobile(String text,ErrorCode errorCode, Object... args) {
		String regex = "((^(13|15|17|18)[0-9]{9}$)|(^0[1,2]{1}\\d{1}-?\\d{8}$)|(^0[3-9] {1}\\d{2}-?\\d{7,8}$)|(^0[1,2]{1}\\d{1}-?\\d{8}-(\\d{1,4})$)|(^0[3-9]{1}\\d{2}-? \\d{7,8}-(\\d{1,4})$))";
		pattern(text, regex, true, errorCode,args);
	}

	/** 正则表达式 */
	public static void pattern(String text, String regex, boolean flag,ErrorCode errorCode, Object... args ) {
		boolean result = false;
		try {
			Pattern pattern = Pattern.compile(regex);
			Matcher matcher = pattern.matcher(text);
			result = matcher.matches();
		} catch (Exception e) {
			result = false;
		}
		if (result != flag) {
			throw Errors.wrap(errorCode,args);
		}
	}


	/**
	 *
	 * @param text 需要校验的值
	 * @param isRequired 是否必填校验
	 * @param minLength 最小长度
	 * @param maxLength 最大长度
	 * @param scEnumList 系统内置校验规则列表，可同时校验多个规则
	 * @param otherRegex 其它规则，正则表达式
	 * @param errorCode 错误编码
	 * @param args 其它说明
	 */
	public static void validateString(String text, Boolean isRequired, Integer minLength, Integer maxLength, List<ValidateRegexEnum> scEnumList, String otherRegex, ErrorCode errorCode, Object... args ){
		if(isRequired){
			isNotEmpty(text, CommonError.EMPTY_VALUE,args);
		}
		if(minLength!=null){
			isNotNull(text, CommonError.EMPTY_VALUE,args);
			if ( text.length() < minLength) {
				throw Errors.wrap(CommonError.LESS_MIN_LENGTH,minLength,args);
			}
		}
		if(maxLength!=null){
			isNotNull(text, CommonError.EMPTY_VALUE,args);
			if ( text.length() > maxLength) {
				throw Errors.wrap(CommonError.GREATER_MAX_LENGTH,maxLength,args);
			}
		}
		if(scEnumList!=null && scEnumList.size()>0){
			for(ValidateRegexEnum scEnum:scEnumList){
				pattern(text, scEnum.getRegex(), true, scEnum.getCommonError(),args);
			}
		}
		if(StringUtils.isNotEmpty(otherRegex)){
			pattern(text, otherRegex, true, errorCode,args);
		}
	}

	public static void validateInteger(Integer integer,Boolean isRequired,Integer minRange,Integer maxRange,Object... args ){
		if(isRequired){
			isNotNull(integer,CommonError.EMPTY_VALUE,args);
		}
		if(minRange!=null){
			min(integer,minRange,CommonError.LESS_MIN_RANGE,args);
		}
		if(maxRange!=null){
			max(integer,maxRange,CommonError.GREATER_MAX_RANGE,args);
		}
	}
}
